
#include "HashMin.h"
#define LARGO  3
         
         HashMin::HashMin(){
             primo = Primo::getInstance();
             vector = (unsigned int*)malloc(sizeof(unsigned int)*DEF_NUM_MINHASH);
             Inicialzar();
         }

         HashMin::~HashMin(){
             
         }

         unsigned long int HashMin::F_Hashing_String(char* codigo)  {
             unsigned long int  valor = 0;
             int cod = 0;
             for(int i=0; i< strlen(codigo); i++){
                 cod = (int)codigo[i];
                 if (cod < 0)
                     cod = cod + 256;
                 valor = valor + pow(256, i) * cod;
             }
             return valor;
         }
         
         int HashMin::F_MinHashing_N(unsigned long int codigo, int coef){
             unsigned long long valor = codigo;
             unsigned long long  porprimo = valor * coef;
             unsigned long long  divisor = DEF_MOD_MINHASH;
             return (porprimo % divisor);
             
             //   return ((coef * codigo * 1.0) % DEF_MOD_MINHASH);
         }
         
         int HashMin::Execute(){
             int hashShingle = 0;
             char* codShingle = (char*)malloc(sizeof(char)*4);
             FILE* archivo = fopen("/home/fliaali/Descargas/Arch1.txt","r");
             while(feof(archivo) == 0){
                fgets(codShingle, 5, archivo);
                hashShingle = F_Hashing_String(codShingle) % DEF_MOD_MINHASH;
                int i=0;
                int valor = 0;
                while (i < DEF_NUM_MINHASH)
                {
                    valor = F_MinHashing_N(hashShingle, primo->GetElem(i));
                    if (vector[i] > valor)
                        vector[i] = valor;
                    i++;
                }
             }
             fclose(archivo);
             free(codShingle);
             return 0;
         }
         
         int HashMin::Execute(char* shingle) {
              //int hashShingle = F_Hashing_String(shingle) % DEF_MOD_MINHASH;
              unsigned long int hashShingle = F_Hashing_String(shingle);
              // Si el resto es cero, me pone en cero todo el minhash
              if (hashShingle == 0)
                  hashShingle++;
              //
              
              int i=0;
              unsigned int valor = 0;
              while (i < DEF_NUM_MINHASH)
                {
                    valor = F_MinHashing_N(hashShingle, primo->GetElem(i));
                    //if (vector[i] > valor)
                    if ((valor > 0) && (vector[i] > valor))
                        vector[i] = valor;
                    i++;
                }
              free(shingle);
         }
         
         void HashMin::Inicialzar(){
             for(int i=0; i< DEF_NUM_MINHASH; i++){
                 vector[i] = DEF_MOD_MINHASH + 2;
                 //vector[i] = DEF_MOD_MINHASH;
             }
         }
         
         char* HashMin::StringPadLeft(char* codigo, int padlen){
             int len = (int) strlen(codigo);
             if (len > padlen)
                 return codigo;
             for (int i=0; i < (padlen-len); i++){
                 strcat(codigo,"0");
             }
             return codigo;
         }
         
         void HashMin::IntToString(int valor, int largoString, char* string){ 
             int ind = largoString -1;
             while(valor>0){
                string[ind] = (char)(valor%10+48);
                valor/=10;
                ind --;
             }
             while(ind>=0){
                string[ind]='0';
                ind--;
             }
             string[largoString]= '\0';
         }
         
         void HashMin::Save(const char* nombreArchivo){
             char cadena[LARGO];
             FILE* fp = fopen(nombreArchivo,"w");
             if(fp==NULL){
                 printf("HashMin - No se pudo crear el archivo %s \n", nombreArchivo);
                 return;
             }
                 
                 
             for(int i=1; i< DEF_NUM_MINHASH; i++){
                 IntToString(vector[i],LARGO,cadena);
                 fputs(cadena, fp);
             }
             fclose(fp);
         }
         
         void HashMin::Destruir(){
             free(vector);
         }
        